package cn.net.isir.service2;

import com.alibaba.fastjson.JSON;
import cn.net.isir.common.XML;
import cn.net.isir.core.BasicService2;
import cn.net.isir.core.SetBasicDao;
import cn.net.isir.dao.WxMinipPayNotifyDao;
import cn.net.isir.dao.WxMinipPayUnifiedOrderInfoDao;
import cn.net.isir.entity.WxMinipPayNotify;
import cn.net.isir.entity.WxMinipPayUnifiedOrderInfo;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.stereotype.Service;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class WxMinipPayNotifyService extends BasicService2<WxMinipPayNotify> {
    @SetBasicDao
    @Resource
    private WxMinipPayNotifyDao wxMinipPayNotifyDao;
    @Resource
    private WxMinipPayUnifiedOrderInfoDao wxMinipPayUnifiedOrderInfoDao;
    @Resource
    private OrderService orderService;

    /**
     * 处理微信支付通知
     *
     * @param result 消息内容
     * @return 通知结果
     */
    public String notify(String result) {
        //将字符串解析成XML
        Document document;
        try {
            document = DocumentHelper.parseText(result);
        } catch (DocumentException e) {
            e.printStackTrace();
            //如果失败返回错误，微信会再次发送支付信息
            XML xml = XML.generateXML("xml");
            xml.addChild("return_code", "FAIL");
            xml.addChild("return_msg", "FAIL");
            return xml.toConvertString();
        }
        //将XML格式转化成MAP格式数据
//                Map<String, Object> resultMap = XmlMapHandle.Dom2Map(doc);
        //后续处理
        Element root = document.getRootElement();
        List elementList = root.elements();
        logger.info(elementList);

        WxMinipPayNotify notify = new WxMinipPayNotify();
        Map<String, Object> typeMap = new HashMap<>();
        Map<String, Object> idMap = new HashMap<>();
        Map<String, Object> feeMap = new HashMap<>();
        XML resultXml = XML.generateXML("xml");
        for (Object elementObj : elementList) {
            Element element = (Element) elementObj;
            if ("return_code".equals(element.getName())) {
                notify.setReturn_code(String.valueOf(element.getData()));
                resultXml.addChild("return_code", String.valueOf(element.getData()));
            }
            if ("return_msg".equals(element.getName())) {
                notify.setReturn_msg(String.valueOf(element.getData()));
                resultXml.addChild("return_msg", String.valueOf(element.getData()));
            }
            if ("appid".equals(element.getName())) {
                notify.setAppid(String.valueOf(element.getData()));
                resultXml.addChild("appid", String.valueOf(element.getData()));
            }
            if ("sub_appid".equals(element.getName())) {
                notify.setSub_appid(String.valueOf(element.getData()));
                resultXml.addChild("sub_appid", String.valueOf(element.getData()));
            }
            if ("sub_mch_id".equals(element.getName())) {
                notify.setSub_mch_id(String.valueOf(element.getData()));
                resultXml.addChild("sub_mch_id", String.valueOf(element.getData()));
            }
            if ("mch_id".equals(element.getName())) {
                notify.setMch_id(String.valueOf(element.getData()));
                resultXml.addChild("mch_id", String.valueOf(element.getData()));
            }
            if ("device_info".equals(element.getName())) {
                notify.setDevice_info(String.valueOf(element.getData()));
                resultXml.addChild("device_info", String.valueOf(element.getData()));
            }
            if ("nonce_str".equals(element.getName())) {
                notify.setNonce_str(String.valueOf(element.getData()));
                resultXml.addChild("nonce_str", String.valueOf(element.getData()));
            }
            if ("sign".equals(element.getName())) {
                notify.setSign(String.valueOf(element.getData()));
//                resultXml.addChild("sign", String.valueOf(element.getData()));
            }
            if ("sign_type".equals(element.getName())) {
                notify.setSign_type(String.valueOf(element.getData()));
                resultXml.addChild("sign_type", String.valueOf(element.getData()));
            }
            if ("result_code".equals(element.getName())) {
                notify.setResult_code(String.valueOf(element.getData()));
                resultXml.addChild("result_code", String.valueOf(element.getData()));
            }
            if ("err_code".equals(element.getName())) {
                notify.setErr_code(String.valueOf(element.getData()));
                resultXml.addChild("err_code", String.valueOf(element.getData()));
            }
            if ("err_code_des".equals(element.getName())) {
                notify.setErr_code_des(String.valueOf(element.getData()));
                resultXml.addChild("err_code_des", String.valueOf(element.getData()));
            }
            if ("openid".equals(element.getName())) {
                notify.setOpenid(String.valueOf(element.getData()));
                resultXml.addChild("openid", String.valueOf(element.getData()));
            }
            if ("is_subscribe".equals(element.getName())) {
                notify.setIs_subscribe(String.valueOf(element.getData()));
                resultXml.addChild("is_subscribe", String.valueOf(element.getData()));
            }
            if ("sub_openid".equals(element.getName())) {
                notify.setSub_openid(String.valueOf(element.getData()));
                resultXml.addChild("sub_openid", String.valueOf(element.getData()));
            }
            if ("sub_is_subscribe".equals(element.getName())) {
                notify.setSub_is_subscribe(String.valueOf(element.getData()));
                resultXml.addChild("sub_is_subscribe", String.valueOf(element.getData()));
            }
            if ("trade_type".equals(element.getName())) {
                notify.setTrade_type(String.valueOf(element.getData()));
                resultXml.addChild("trade_type", String.valueOf(element.getData()));
            }
            if ("bank_type".equals(element.getName())) {
                notify.setBank_type(String.valueOf(element.getData()));
                resultXml.addChild("bank_type", String.valueOf(element.getData()));
            }
            if ("total_fee".equals(element.getName())) {
                notify.setTotal_fee(String.valueOf(element.getData()));
                resultXml.addChild("total_fee", String.valueOf(element.getData()));
            }
            if ("fee_type".equals(element.getName())) {
                notify.setFee_type(String.valueOf(element.getData()));
                resultXml.addChild("fee_type", String.valueOf(element.getData()));
            }
            if ("cash_fee".equals(element.getName())) {
                notify.setCash_fee(String.valueOf(element.getData()));
                resultXml.addChild("cash_fee", String.valueOf(element.getData()));
            }
            if ("cash_fee_type".equals(element.getName())) {
                notify.setCash_fee_type(String.valueOf(element.getData()));
                resultXml.addChild("cash_fee_type", String.valueOf(element.getData()));
            }
            if ("settlement_total_fee".equals(element.getName())) {
                notify.setSettlement_total_fee(String.valueOf(element.getData()));
                resultXml.addChild("settlement_total_fee", String.valueOf(element.getData()));
            }
            if ("coupon_fee".equals(element.getName())) {
                notify.setCoupon_fee(String.valueOf(element.getData()));
                resultXml.addChild("coupon_fee", String.valueOf(element.getData()));
            }
            if ("coupon_count".equals(element.getName())) {
                notify.setCoupon_count(String.valueOf(element.getData()));
                resultXml.addChild("coupon_count", String.valueOf(element.getData()));
            }
//            if ("coupon_type_".equals(element.getName())) {
//                notify.setCoupon_type_(String.valueOf(element.getData()));
//                resultXml.addChild("coupon_type_", String.valueOf(element.getData()));
//            }
//            if ("coupon_id_".equals(element.getName())) {
//                notify.setCoupon_id_(String.valueOf(element.getData()));
//                resultXml.addChild("coupon_id_", String.valueOf(element.getData()));
//            }
//            if ("coupon_fee_".equals(element.getName())) {
//                notify.setCoupon_fee_(String.valueOf(element.getData()));
//                resultXml.addChild("coupon_fee_", String.valueOf(element.getData()));
//            }
            if (element.getName().startsWith("coupon_type_")) {
                typeMap.put(element.getName(), element.getData());
                resultXml.addChild(element.getName(), String.valueOf(element.getData()));
            }
            if (element.getName().startsWith("coupon_id_")) {
                idMap.put(element.getName(), element.getData());
                resultXml.addChild(element.getName(), String.valueOf(element.getData()));
            }
            if (element.getName().startsWith("coupon_fee_")) {
                feeMap.put(element.getName(), element.getData());
                resultXml.addChild(element.getName(), String.valueOf(element.getData()));
            }
            if ("transaction_id".equals(element.getName())) {
                notify.setTransaction_id(String.valueOf(element.getData()));
                resultXml.addChild("transaction_id", String.valueOf(element.getData()));
            }
            if ("out_trade_no".equals(element.getName())) {
                notify.setOut_trade_no(String.valueOf(element.getData()));
                resultXml.addChild("out_trade_no", String.valueOf(element.getData()));
            }
            if ("attach".equals(element.getName())) {
                notify.setAttach(String.valueOf(element.getData()));
                resultXml.addChild("attach", String.valueOf(element.getData()));
            }
            if ("time_end".equals(element.getName())) {
                notify.setTime_end(String.valueOf(element.getData()));
                resultXml.addChild("time_end", String.valueOf(element.getData()));
            }
            if ("remark".equals(element.getName())) {
                notify.setRemark(String.valueOf(element.getData()));
                resultXml.addChild("remark", String.valueOf(element.getData()));
            }
            if ("status".equals(element.getName())) {
                notify.setStatus(String.valueOf(element.getData()));
                resultXml.addChild("status", String.valueOf(element.getData()));
            }
            if ("createUser".equals(element.getName())) {
                notify.setCreateUser(String.valueOf(element.getData()));
                resultXml.addChild("createUser", String.valueOf(element.getData()));
            }
        }
        notify.setCoupon_type_(JSON.toJSONString(typeMap));
        notify.setCoupon_id_(JSON.toJSONString(idMap));
        notify.setCoupon_fee_(JSON.toJSONString(feeMap));

        if (!notify.getSign().equals(resultXml.sign())) {
            //如果失败返回错误，微信会再次发送支付信息
            XML xml = XML.generateXML("xml");
            xml.addChild("return_code", "FAIL");
            xml.addChild("return_msg", "SIGN ERROR");
            return xml.toConvertString();
        }

        //获取预下单信息
        WxMinipPayUnifiedOrderInfo orderInfo = new WxMinipPayUnifiedOrderInfo();
        orderInfo.setOut_trade_no(notify.getOut_trade_no());
        orderInfo = wxMinipPayUnifiedOrderInfoDao.selectOne(orderInfo);
        orderInfo.setStatus("paid");
        //更新预下单信息
        wxMinipPayUnifiedOrderInfoDao.update(orderInfo);
        //插入通知
        int i = wxMinipPayNotifyDao.insert(notify);
        if (i <= 0) {
            throw new RuntimeException("支付通知保存失败");
        }

        if ("SUCCESS".equals(notify.getReturn_code()) && "SUCCESS".equals(notify.getResult_code())) {
            //调用支付成功的业务操作
            boolean handleResult = orderService.paidOrderHandle(orderInfo.getOut_trade_no(), orderInfo.getCreateUser(), "wx-minip-pay", "wx");
            if (!handleResult) {
                //手动回滚操作
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                //如果失败返回错误，微信会再次发送支付信息
                XML xml = XML.generateXML("xml");
                xml.addChild("return_code", "FAIL");
                xml.addChild("return_msg", "FAIL");
                return xml.toConvertString();
            }
        }
        //通知微信支付系统接收到信息
        XML xml = XML.generateXML("xml");
        xml.addChild("return_code", "SUCCESS");
        xml.addChild("return_msg", "SUCCESS");
        return xml.toConvertString();
    }
}
